/**
 * 请求队列管理器
 * 负责管理请求队列，支持优先级、最大并发数等特性
 */
class RequestQueue {
  /**
   * 构造函数
   * @param {Object} options 队列选项
   * @param {Number} options.maxConcurrent 最大并发请求数
   * @param {Number} options.priorityLevels 优先级等级数
   */
  constructor(options = {}) {
    // 配置选项
    this.config = {
      maxConcurrent: options.maxConcurrent || 6,
      priorityLevels: options.priorityLevels || 3
    };
    
    // 初始化队列 (按优先级分组)
    this.queues = Array(this.config.priorityLevels)
      .fill(0)
      .map(() => []);
    
    // 活跃任务映射和计数
    this.activeCount = 0;
    this.activeMap = new Map();
    
    // 请求ID到任务的映射
    this.taskMap = new Map();
    
    // 全局终止控制器
    this.abortController = new AbortController();
  }
  
  /**
   * 更新队列配置
   * @param {Object} config 新的配置
   */
  setConfig(config = {}) {
    if (config.maxConcurrent !== undefined) {
      this.config.maxConcurrent = config.maxConcurrent;
    }
    
    if (config.priorityLevels !== undefined) {
      // 如果优先级等级数变化，需要重新调整队列
      const oldLevels = this.config.priorityLevels;
      const newLevels = config.priorityLevels;
      
      if (newLevels > oldLevels) {
        // 增加优先级等级
        const newQueues = Array(newLevels - oldLevels)
          .fill(0)
          .map(() => []);
        this.queues = [...this.queues, ...newQueues];
      } else if (newLevels < oldLevels) {
        // 减少优先级等级，将高优先级的任务合并到低优先级
        for (let i = newLevels; i < oldLevels; i++) {
          this.queues[newLevels - 1].push(...this.queues[i]);
        }
        this.queues = this.queues.slice(0, newLevels);
      }
      
      this.config.priorityLevels = newLevels;
    }
  }
  
  /**
   * 添加任务到队列
   * @param {Function} task 任务函数
   * @param {Object} options 任务选项
   * @param {Number} options.priority 优先级 (0为最高)
   * @param {String} options.requestId 请求ID
   * @param {Number} options.timeout 超时时间
   * @returns {Promise} 任务执行结果
   */
  add(task, options = {}) {
    return new Promise((resolve, reject) => {
      // 处理选项
      const priority = typeof options.priority === 'number'
        ? Math.min(Math.max(options.priority, 0), this.config.priorityLevels - 1)
        : this.config.priorityLevels - 1; // 默认最低优先级
      
      const requestId = options.requestId || `task_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
      const timeout = options.timeout || 0;
      
      // 创建任务包装
      const taskWrapper = {
        id: requestId,
        priority,
        timestamp: Date.now(),
        run: async () => {
          try {
            // 标记为活跃
            this.activeCount++;
            this.activeMap.set(requestId, true);
            
            // 创建超时控制
            let timeoutId;
            let timeoutPromise = Promise.resolve();
            
            if (timeout > 0) {
              timeoutPromise = new Promise((_, timeoutReject) => {
                timeoutId = setTimeout(() => {
                  timeoutReject(new Error(`Request timeout after ${timeout}ms`));
                }, timeout);
              });
            }
            
            // 执行任务，并处理超时
            try {
              const result = await Promise.race([
                task(),
                timeoutPromise
              ]);
              
              // 清除超时
              if (timeoutId) clearTimeout(timeoutId);
              
              // 解析结果
              resolve(result);
            } catch (error) {
              // 清除超时
              if (timeoutId) clearTimeout(timeoutId);
              
              // 拒绝承诺
              reject(error);
            }
          } finally {
            // 清理状态
            this.activeCount--;
            this.activeMap.delete(requestId);
            this.taskMap.delete(requestId);
            
            // 处理下一个任务
            this._processQueue();
          }
        }
      };
      
      // 将任务添加到合适的队列
      this.queues[priority].push(taskWrapper);
      
      // 保存任务引用
      this.taskMap.set(requestId, taskWrapper);
      
      // 尝试处理队列
      this._processQueue();
    });
  }
  
  /**
   * 处理队列，执行等待中的任务
   * @private
   */
  _processQueue() {
    // 如果已达到最大并发数，则不处理
    if (this.activeCount >= this.config.maxConcurrent) {
      return;
    }
    
    // 查找最高优先级的等待任务
    let highestPriorityTask = null;
    let highestPriorityQueueIndex = -1;
    
    for (let i = 0; i < this.config.priorityLevels; i++) {
      if (this.queues[i].length > 0) {
        highestPriorityTask = this.queues[i][0];
        highestPriorityQueueIndex = i;
        break;
      }
    }
    
    // 如果没有任务，则返回
    if (!highestPriorityTask) {
      return;
    }
    
    // 从队列中移除任务
    this.queues[highestPriorityQueueIndex].shift();
    
    // 执行任务
    highestPriorityTask.run();
  }
  
  /**
   * 从队列中移除指定ID的任务
   * @param {String} requestId 任务ID
   * @returns {Boolean} 是否成功移除
   */
  remove(requestId) {
    // 检查任务是否在映射中
    const task = this.taskMap.get(requestId);
    if (!task) {
      return false;
    }
    
    // 从队列中移除
    const queueIndex = task.priority;
    const taskIndex = this.queues[queueIndex].findIndex(t => t.id === requestId);
    
    if (taskIndex !== -1) {
      this.queues[queueIndex].splice(taskIndex, 1);
      this.taskMap.delete(requestId);
      return true;
    }
    
    return false;
  }
  
  /**
   * 清空所有队列
   */
  clear() {
    // 清空所有队列
    this.queues.forEach(queue => queue.length = 0);
    
    // 清空任务映射
    this.taskMap.clear();
  }
  
  /**
   * 获取队列中的任务数
   * @returns {Number} 任务数
   */
  getQueueSize() {
    return this.queues.reduce((total, queue) => total + queue.length, 0);
  }
  
  /**
   * 获取活跃任务数
   * @returns {Number} 活跃任务数
   */
  getActiveCount() {
    return this.activeCount;
  }
  
  /**
   * 获取队列状态
   * @returns {Object} 队列状态
   */
  getStatus() {
    return {
      active: this.activeCount,
      queued: this.getQueueSize(),
      priorityQueues: this.queues.map(queue => queue.length),
      config: { ...this.config }
    };
  }
}

export default RequestQueue; 